import json
import base64
import cv2
import os
import time
import random
import boto3
from boto3.dynamodb.conditions import Key, Attr


def get_data_endpoint(kinesis_client):
    response = kinesis_client.get_data_endpoint(
        StreamARN='arn:aws:kinesisvideo:us-east-1:292220080392:stream/smart-door/1604536197203', APIName='GET_MEDIA'
    )

    return response


def get_byte_stream_from_kinesis(video_client):
    response = video_client.get_media(
        StreamARN='arn:aws:kinesisvideo:us-east-1:292220080392:stream/smart-door/1604536197203',
        StartSelector={'StartSelectorType': 'NOW'}
    )

    payload = response['Payload']

    return payload


def lambda_handler(event, context):
    if int(time.time()) % 60 > 20:
        return

    # TODO implement
    # LF1 check whether there is faceId from KDS
    # pull byte stream from kds and decide whether the face in rekognition collectoin
    data_raw = event['Records'][0]['kinesis']['data']
    data_str = base64.b64decode(data_raw).decode('ASCII')
    img_name = 'test.jpg'

    dynamodb = boto3.resource('dynamodb')
    sns = boto3.client('sns')
    kinesis_client = boto3.client('kinesisvideo', region_name='us-east-1')
    data_end_point = get_data_endpoint(kinesis_client)
    video_client = boto3.client('kinesis-video-media', endpoint_url=data_end_point['DataEndpoint'],
                                region_name='us-east-1')
    s3 = boto3.client('s3', region_name='us-east-1')
    faceId = None

    try:
        data = json.loads(data_str)
    except:
        return 'error! not a json'
    print(data)
    if len(data['FaceSearchResponse']) != 0 and len(data['FaceSearchResponse'][0]['MatchedFaces']) != 0:
        faceId = data['FaceSearchResponse'][0]['MatchedFaces'][0]['Face']['FaceId']
        img_name = time.strftime("%Y-%m-%d_%H.%M.%S", time.localtime()) + '.jpg'

        passcodes_table = dynamodb.Table('passcodes')
        # if otp already exists, directly return
        res = passcodes_table.scan(
            FilterExpression=Attr('faceId').eq(faceId)
        )
        if len(res['Items']) != 0:
            return

        # if known, append photo and get phone number
        visitors_table = dynamodb.Table('visitors')

        response = visitors_table.scan(
            FilterExpression=Attr('faceId').eq(faceId)
        )

        print('response', response)

        people = response["Items"][0]
        photos = people['photo']
        phoneNumber = people['phoneNumber']
        photos += ',' + img_name

        visitors_table.put_item(
            Item={
                'name': people['name'],
                'phoneNumber': phoneNumber,
                'faceId': faceId,
                'photo': photos,
            }
        )
        img_name = faceId + '/' + img_name

        # generate otp and store in DB1 with TTL=5min
        otp = random.randint(1000, 9999)
        ttl = int(time.time()) + 5 * 60
        passcodes_table.put_item(
            Item={
                'otp': otp,
                'faceId': faceId,
                'ttl': ttl
            }
        )

        print('done')

        # send otp to visitor's phone
        # sns.publish(
        #     PhoneNumber='+1'+phoneNumber,
        #     Message='Your one time passcode: ' + str(otp)
        # )
    else:
        print('else')
        # sns.publish(
        #     PhoneNumber='+1'+'8018679834',
        #     Message='New visitor coming! ' + 'http://columbia-hw2-tt2756.s3-website-us-east-1.amazonaws.com/'
        # )

    # pull video from kvs and extract the photo

    video_binary_string = get_byte_stream_from_kinesis(video_client).read(amt=1024000)

    with open('/tmp/video.mp4', 'wb') as wfile:
        wfile.write(video_binary_string)

    cap = cv2.VideoCapture('/tmp/video.mp4')
    success, frame = cap.read()

    cv2.imwrite('/tmp/output.jpg', frame)

    # print('tmp', os.listdir('/tmp'))

    # upload the photo to s3
    s3.upload_file('/tmp/output.jpg', "columbia-hw2-tt2756", img_name, ExtraArgs={'ACL': 'public-read'})

    # print(os.listdir('/tmp'))

    # always store s3 in it
    # get the image
    # get the byte stream

    # receive from kds



